home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_xfig.idb / usr / freeware / src / xfig / transfig.3.1.2 / fig2dev / bound.c.z / bound.c
Encoding:
C/C++ Source or Header  |  1997-09-09  |  14.4 KB  |  504 lines

  1. /*
  2.  * TransFig: Facility for Translating Fig code
  3.  * Copyright (c) 1985 Supoj Sutantavibul
  4.  * Copyright (c) 1991 Micah Beck
  5.  *
  6.  * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  7.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  8.  * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  9.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  10.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  11.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  12.  * PERFORMANCE OF THIS SOFTWARE.
  13.  *
  14.  * The X Consortium, and any party obtaining a copy of these files from
  15.  * the X Consortium, directly or indirectly, is granted, free of charge, a
  16.  * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
  17.  * nonexclusive right and license to deal in this software and
  18.  * documentation files (the "Software"), including without limitation the
  19.  * rights to use, copy, modify, merge, publish, distribute, sublicense,
  20.  * and/or sell copies of the Software, and to permit persons who receive
  21.  * copies from any such party to do so, with the only requirement being
  22.  * that this copyright notice remain intact.  This license includes without
  23.  * limitation a license to do the foregoing actions under any patents of
  24.  * the party supplying this software to the X Consortium.
  25.  */
  26.  
  27. #include <stdio.h>
  28. #include <math.h>
  29. #include "pi.h"
  30. #include "fig2dev.h"
  31. #include "object.h"
  32.  
  33. #define        Ninety_deg        M_PI_2
  34. #define        One_eighty_deg        M_PI
  35. #define        Two_seventy_deg        (M_PI + M_PI_2)
  36. #define        Three_sixty_deg        (M_PI + M_PI)
  37. #define        half(z1 ,z2)        ((z1+z2)/2.0)
  38. #define        max(a, b)        (((a) > (b)) ? (a) : (b))
  39. #define        min(a, b)        (((a) < (b)) ? (a) : (b))
  40.  
  41. arc_bound(arc, xmin, ymin, xmax, ymax)
  42. F_arc    *arc;
  43. int    *xmin, *ymin, *xmax, *ymax;
  44. {
  45.     double    alpha, beta;
  46.     double    dx, dy, radius;
  47.     int    bx, by, sx, sy;
  48.  
  49.     dx = arc->point[0].x - arc->center.x;
  50.     dy = arc->center.y - arc->point[0].y;
  51.     alpha = atan2(dy, dx);
  52.     if (alpha < 0.0) alpha += Three_sixty_deg;
  53.     /* compute_angle returns value between 0 to 2PI */
  54.     
  55.     radius = hypot(dx, dy);
  56.  
  57.     dx = arc->point[2].x - arc->center.x;
  58.     dy = arc->center.y - arc->point[2].y;
  59.     beta = atan2(dy, dx);
  60.     if (beta < 0.0) beta += Three_sixty_deg;
  61.  
  62.     bx = max(arc->point[0].x, arc->point[1].x);
  63.     bx = max(arc->point[2].x, bx);
  64.     by = max(arc->point[0].y, arc->point[1].y);
  65.     by = max(arc->point[2].y, by);
  66.     sx = min(arc->point[0].x, arc->point[1].x);
  67.     sx = min(arc->point[2].x, sx);
  68.     sy = min(arc->point[0].y, arc->point[1].y);
  69.     sy = min(arc->point[2].y, sy);
  70.  
  71.     if (arc->direction == 1) { /* counter clockwise */
  72.         if (alpha > beta) {
  73.         if (alpha <= 0 || 0 <= beta)
  74.             bx = (int)(arc->center.x + radius + 1.0);
  75.         if (alpha <= Ninety_deg || Ninety_deg <= beta)
  76.             sy = (int)(arc->center.y - radius - 1.0);
  77.         if (alpha <= One_eighty_deg || One_eighty_deg <= beta)
  78.             sx = (int)(arc->center.x - radius - 1.0);
  79.         if (alpha <= Two_seventy_deg || Two_seventy_deg <= beta)
  80.             by = (int)(arc->center.y + radius + 1.0);
  81.         }
  82.         else {
  83.         if (0 <= beta && alpha <= 0)
  84.             bx = (int)(arc->center.x + radius + 1.0);
  85.         if (Ninety_deg <= beta && alpha <= Ninety_deg)
  86.             sy = (int)(arc->center.y - radius - 1.0);
  87.         if (One_eighty_deg <= beta && alpha <= One_eighty_deg)
  88.             sx = (int)(arc->center.x - radius - 1.0);
  89.         if (Two_seventy_deg <= beta && alpha <= Two_seventy_deg)
  90.             by = (int)(arc->center.y + radius + 1.0);
  91.         }
  92.         }
  93.     else {    /* clockwise    */
  94.         if (alpha > beta) {
  95.         if (beta <= 0 && 0 <= alpha)
  96.             bx = (int)(arc->center.x + radius + 1.0);
  97.         if (beta <= Ninety_deg && Ninety_deg <= alpha)
  98.             sy = (int)(arc->center.y - radius - 1.0);
  99.         if (beta <= One_eighty_deg && One_eighty_deg <= alpha)
  100.             sx = (int)(arc->center.x - radius - 1.0);
  101.         if (beta <= Two_seventy_deg && Two_seventy_deg <= alpha)
  102.             by = (int)(arc->center.y + radius + 1.0);
  103.         }
  104.         else {
  105.         if (0 <= alpha || beta <= 0)
  106.             bx = (int)(arc->center.x + radius + 1.0);
  107.         if (Ninety_deg <= alpha || beta <= Ninety_deg)
  108.             sy = (int)(arc->center.y - radius - 1.0);
  109.         if (One_eighty_deg <= alpha || beta <= One_eighty_deg)
  110.             sx = (int)(arc->center.x - radius - 1.0);
  111.         if (Two_seventy_deg <= alpha || beta <= Two_seventy_deg)
  112.             by = (int)(arc->center.y + radius + 1.0);
  113.         }
  114.         }
  115.     *xmax = bx; *ymax = by;
  116.     *xmin = sx; *ymin = sy;
  117.     }
  118.  
  119. compound_bound(compound, xmin, ymin, xmax, ymax, include)
  120. F_compound    *compound;
  121. int        *xmin, *ymin, *xmax, *ymax;
  122. int        include;
  123. {
  124.     F_arc        *a;
  125.     F_ellipse    *e;
  126.     F_compound    *c;
  127.     F_spline    *s;
  128.     F_line        *l;
  129.     F_text        *t;
  130.     int        bx, by, sx, sy, first = 1;
  131.     int        llx, lly, urx, ury;
  132.     int            half_wd;
  133.  
  134.     while(compound != NULL) {
  135.     for (a = compound->arcs; a != NULL; a = a->next) {
  136.         arc_bound(a, &sx, &sy, &bx, &by);
  137.             half_wd = (a->thickness + 1) / 2;
  138.         if (first) {
  139.         first = 0;
  140.         llx = sx - half_wd; lly = sy - half_wd;
  141.         urx = bx + half_wd; ury = by + half_wd;
  142.         }
  143.         else {
  144.         llx = min(llx, sx - half_wd); lly = min(lly, sy - half_wd);
  145.         urx = max(urx, bx + half_wd); ury = max(ury, by + half_wd);
  146.         }
  147.         }
  148.  
  149.     if (compound->compounds) {
  150.         compound_bound(compound->compounds, &sx, &sy, &bx, &by, include);
  151.         if (first) {
  152.         first = 0;
  153.         llx = sx; lly = sy;
  154.         urx = bx; ury = by;
  155.         }
  156.         else {
  157.         llx = min(llx, sx); lly = min(lly, sy);
  158.         urx = max(urx, bx); ury = max(ury, by);
  159.         }
  160.         }
  161.  
  162.     for (e = compound->ellipses; e != NULL; e = e->next) {
  163.         ellipse_bound(e, &sx, &sy, &bx, &by);
  164.         if (first) {
  165.         first = 0;
  166.         llx = sx; lly = sy;
  167.         urx = bx; ury = by;
  168.         }
  169.         else {
  170.         llx = min(llx, sx); lly = min(lly, sy);
  171.         urx = max(urx, bx); ury = max(ury, by);
  172.         }
  173.         }
  174.  
  175.     for (l = compound->lines; l != NULL; l = l->next) {
  176.         line_bound(l, &sx, &sy, &bx, &by);
  177.             half_wd = ceil((double)(l->thickness+1) / sqrt(2.0)); 
  178.             /* leave space for corners, better approach needs much more math! */
  179.         if (first) {
  180.         first = 0;
  181.         llx = sx - half_wd; lly = sy - half_wd;
  182.         urx = bx + half_wd; ury = by + half_wd;
  183.         }
  184.         else {
  185.         llx = min(llx, sx - half_wd); lly = min(lly, sy - half_wd);
  186.         urx = max(urx, bx + half_wd); ury = max(ury, by + half_wd);
  187.         }
  188.         }
  189.  
  190.     for (s = compound->splines; s != NULL; s = s->next) {
  191.         spline_bound(s, &sx, &sy, &bx, &by);
  192.             half_wd = (s->thickness+1) / 2;
  193.         if (first) {
  194.         first = 0;
  195.         llx = sx - half_wd; lly = sy - half_wd;
  196.         urx = bx + half_wd; ury = by + half_wd;
  197.         }
  198.         else {
  199.         llx = min(llx, sx - half_wd); lly = min(lly, sy - half_wd);
  200.         urx = max(urx, bx + half_wd); ury = max(ury, by + half_wd);
  201.         }
  202.         }
  203.  
  204.     for (t = compound->texts; t != NULL; t = t->next) {
  205.         text_bound(t, &sx, &sy, &bx, &by, include);
  206.         if (first) {
  207.         first = 0;
  208.         llx = sx; lly = sy;
  209.         urx = bx; ury = by;
  210.         }
  211.         else {
  212.         llx = min(llx, sx); lly = min(lly, sy);
  213.         urx = max(urx, bx); ury = max(ury, by);
  214.         }
  215.         }
  216.         compound = compound->next;
  217.     }
  218.  
  219.     *xmin = llx; *ymin = lly;
  220.     *xmax = urx; *ymax = ury;
  221. }
  222.  
  223. ellipse_bound(e, xmin, ymin, xmax, ymax)
  224. F_ellipse    *e;
  225. int        *xmin, *ymin, *xmax, *ymax;
  226.     /* stolen from xfig-2.1.8 max2 from xfig == max here*/
  227.  
  228.     int        half_wd;
  229.     double        c1, c2, c3, c4, c5, c6, v1, cphi, sphi, cphisqr, sphisqr;
  230.     double        xleft, xright, d, asqr, bsqr;
  231.     int        yymax, yy=0;
  232.     float        xcen, ycen, a, b; 
  233.  
  234.     xcen = e->center.x;
  235.     ycen = e->center.y;
  236.     a = e->radiuses.x;
  237.     b = e->radiuses.y;
  238.     if (a==0 || b==0) {
  239.         *xmin = *xmax = xcen;
  240.         *ymin = *ymax = ycen;
  241.         return;
  242.     }
  243.  
  244.     cphi = cos((double)e->angle);
  245.     sphi = sin((double)e->angle);
  246.     cphisqr = cphi*cphi;
  247.     sphisqr = sphi*sphi;
  248.     asqr = a*a;
  249.     bsqr = b*b;
  250.     
  251.     c1 = (cphisqr/asqr)+(sphisqr/bsqr);
  252.     c2 = ((cphi*sphi/asqr)-(cphi*sphi/bsqr))/c1;
  253.     c3 = (bsqr*cphisqr) + (asqr*sphisqr);
  254.     yymax = sqrt(c3);
  255.     c4 = a*b/c3;
  256.     c5 = 0;
  257.     v1 = c4*c4;
  258.     c6 = 2*v1;
  259.     c3 = c3*v1-v1;
  260.     /* odd first points */
  261.     *xmin = *ymin =  100000;
  262.     *xmax = *ymax = -100000;
  263.     if (yymax % 2) {
  264.         d = sqrt(c3);
  265.         *xmin = min(*xmin,xcen-ceil(d));
  266.         *xmax = max(*xmax,xcen+ceil(d));
  267.         *ymin = min(*ymin,ycen);
  268.         *ymax = max(*ymax,ycen);
  269.         c5 = c2;
  270.         yy=1;
  271.     }
  272.     while (c3>=0) {
  273.         d = sqrt(c3);
  274.         xleft = c5-d;
  275.         xright = c5+d;                        
  276.         *xmin = min(*xmin,xcen+floor(xleft));
  277.         *xmax = max(*xmax,xcen+ceil(xleft));
  278.         *ymax = max(*ymax,ycen+yy);
  279.         *xmin = min(*xmin,xcen+floor(xright));
  280.         *xmax = max(*xmax,xcen+ceil(xright));
  281.         *ymax = max(*ymax,ycen+yy);
  282.         *xmin = min(*xmin,xcen-ceil(xright));
  283.         *xmax = max(*xmax,xcen-floor(xright));
  284.         *ymin = min(*ymin,ycen-yy);
  285.         *xmin = min(*xmin,xcen-ceil(xleft));
  286.         *xmax = max(*xmax,xcen-floor(xleft));
  287.         *ymin = min(*ymin,ycen-yy);
  288.         c5+=c2;
  289.         v1+=c6;
  290.         c3-=v1;
  291.         yy=yy+1;
  292.     }
  293.     /* for simplicity, just add half the line thickness to xmax and ymax
  294.        and subtract half from xmin and ymin */
  295.     half_wd = (e->thickness+1)/2; /*correct for integer division */
  296.     *xmax += half_wd;
  297.     *ymax += half_wd;
  298.     *xmin -= half_wd;
  299.     *ymin -= half_wd;
  300.     }
  301.  
  302. line_bound(l, xmin, ymin, xmax, ymax)
  303. F_line    *l;
  304. int    *xmin, *ymin, *xmax, *ymax;
  305. {
  306.     points_bound(l->points, xmin, ymin, xmax, ymax);
  307.     }
  308.  
  309. spline_bound(s, xmin, ymin, xmax, ymax)
  310. F_spline    *s;
  311. int        *xmin, *ymin, *xmax, *ymax;
  312. {
  313.     if (int_spline(s)) {
  314.         int_spline_bound(s, xmin, ymin, xmax, ymax);
  315.         }
  316.     else {
  317.         normal_spline_bound(s, xmin, ymin, xmax, ymax);
  318.         }
  319.     }
  320.  
  321. int_spline_bound(s, xmin, ymin, xmax, ymax)
  322. F_spline    *s;
  323. int        *xmin, *ymin, *xmax, *ymax;
  324. {
  325.     F_point        *p1, *p2;
  326.     F_control    *cp1, *cp2;
  327.     double        x0, y0, x1, y1, x2, y2, x3, y3, sx1, sy1, sx2, sy2;
  328.     double        tx, ty, tx1, ty1, tx2, ty2;
  329.     double        sx, sy, bx, by;
  330.  
  331.     p1 = s->points;
  332.     sx = bx = p1->x;
  333.     sy = by = p1->y;
  334.     cp1 = s->controls;
  335.     for (p2 = p1->next, cp2 = cp1->next; p2 != NULL;
  336.         p1 = p2, cp1 = cp2, p2 = p2->next, cp2 = cp2->next) {
  337.         x0 = p1->x; y0 = p1->y;
  338.         x1 = cp1->rx; y1 = cp1->ry;
  339.         x2 = cp2->lx; y2 = cp2->ly;
  340.         x3 = p2->x; y3 = p2->y;
  341.         tx = half(x1, x2); ty = half(y1, y2);
  342.         sx1 = half(x0, x1); sy1 = half(y0, y1);
  343.         sx2 = half(sx1, tx); sy2 = half(sy1, ty);
  344.         tx2 = half(x2, x3); ty2 = half(y2, y3);
  345.         tx1 = half(tx2, tx); ty1 = half(ty2, ty);
  346.  
  347.         sx = min(x0, sx); sy = min(y0, sy);
  348.         sx = min(sx1, sx); sy = min(sy1, sy);
  349.         sx = min(sx2, sx); sy = min(sy2, sy);
  350.         sx = min(tx1, sx); sy = min(ty1, sy);
  351.         sx = min(tx2, sx); sy = min(ty2, sy);
  352.         sx = min(x3, sx); sy = min(y3, sy);
  353.  
  354.         bx = max(x0, bx); by = max(y0, by);
  355.         bx = max(sx1, bx); by = max(sy1, by);
  356.         bx = max(sx2, bx); by = max(sy2, by);
  357.         bx = max(tx1, bx); by = max(ty1, by);
  358.         bx = max(tx2, bx); by = max(ty2, by);
  359.         bx = max(x3, bx); by = max(y3, by);
  360.         }
  361.     *xmin = round(sx);
  362.     *ymin = round(sy);
  363.     *xmax = round(bx);
  364.     *ymax = round(by);
  365.     }
  366.  
  367. normal_spline_bound(s, xmin, ymin, xmax, ymax)
  368. F_spline    *s;
  369. int        *xmin, *ymin, *xmax, *ymax;
  370. {
  371.     F_point    *p;
  372.     double    cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
  373.     double    x1, y1, x2, y2, sx, sy, bx, by;
  374.     double    px, py, qx, qy;
  375.  
  376.     p = s->points;
  377.     x1 = p->x;  y1 = p->y;
  378.     p = p->next;
  379.     x2 = p->x;  y2 = p->y;
  380.     cx1 = (x1 + x2) / 2.0;   cy1 = (y1 + y2) / 2.0;
  381.     cx2 = (cx1 + x2) / 2.0;  cy2 = (cy1 + y2) / 2.0;
  382.     if (closed_spline(s)) {
  383.         x1 = (cx1 + x1) / 2.0;
  384.         y1 = (cy1 + y1) / 2.0;
  385.         }
  386.     sx = min(x1, cx2); sy = min(y1, cy2);
  387.     bx = max(x1, cx2); by = max(y1, cy2);
  388.  
  389.     for (p = p->next; p != NULL; p = p->next) {
  390.         x1 = x2;  y1 = y2;
  391.         x2 = p->x;  y2 = p->y;
  392.         cx4 = (x1 + x2) / 2.0; cy4 = (y1 + y2) / 2.0;
  393.         cx3 = (x1 + cx4) / 2.0; cy3 = (y1 + cy4) / 2.0;
  394.         cx2 = (cx4 + x2) / 2.0;  cy2 = (cy4 + y2) / 2.0;
  395.  
  396.         px = min(cx2, cx3); py = min(cy2, cy3);
  397.         qx = max(cx2, cx3); qy = max(cy2, cy3);
  398.  
  399.         sx = min(sx, px); sy = min(sy, py);
  400.         bx = max(bx, qx); by = max(by, qy);
  401.         }
  402.     if (closed_spline(s)) {
  403.         *xmin = floor(sx );
  404.         *ymin = floor(sy );
  405.         *xmax = ceil (bx );
  406.         *ymax = ceil (by );
  407.         }
  408.     else {
  409.         *xmin = floor(min(sx, x2) );
  410.         *ymin = floor(min(sy, y2) );
  411.         *xmax = ceil (max(bx, x2) );
  412.         *ymax = ceil (max(by, y2) );
  413.         }
  414.     }
  415.  
  416. double rot_x(x,y,angle) 
  417. double x,y,angle;
  418. {
  419.     return(x*cos(-angle)-y*sin(-angle));
  420. }
  421.  
  422. double rot_y(x,y,angle)
  423. double x,y,angle;
  424. {
  425.  return(x*sin(-angle)+y*cos(-angle));
  426. }
  427.  
  428.  
  429. text_bound(t, xmin, ymin, xmax, ymax, include)
  430. F_text    *t;
  431. int    *xmin, *ymin, *xmax, *ymax;
  432. int    include;
  433. {
  434.     double dx1, dx2, dx3, dx4, dy1, dy2, dy3, dy4;
  435.     /* characters have some extent downside */
  436.     if (t->type == T_CENTER_JUSTIFIED) {
  437.         dx1 = (t->length/1.95);     dy1 =  0.2*t->height;
  438.         dx2 = -(t->length/1.95);    dy2 =  0.2*t->height;
  439.         dx3 = (t->length/1.95);     dy3 = -0.8*t->height;
  440.         dx4 = -(t->length/1.95);    dy4 = -0.8*t->height;
  441.     } else if (t->type == T_RIGHT_JUSTIFIED) {
  442.         dx1 = 0.0;                      dy1 =  0.2*t->height;
  443.         dx2 = -t->length*1.0256;        dy2 =  0.2*t->height;
  444.         dx3 = 0.0;                      dy3 = -0.8*t->height;
  445.         dx4 = -t->length*1.0256;        dy4 = -0.8*t->height;
  446.     } else {
  447.         dx1 = (include ? t->length*1.0256 : 0); dy1 =  0.2*t->height;
  448.         dx2 = 0.0;                              dy2 =  0.2*t->height;
  449.         dx3 = (include ? t->length*1.0256 : 0); dy3 = -0.8*t->height;
  450.         dx4 = 0.0;                              dy4 = -0.8*t->height;
  451.     }
  452.     *xmax= t->base_x +
  453.            max( max( rot_x(dx1,dy1,t->angle), rot_x(dx2,dy2,t->angle) ), 
  454.             max( rot_x(dx3,dy3,t->angle), rot_x(dx4,dy4,t->angle) ) );
  455.     *ymax= t->base_y + 
  456.            max( max( rot_y(dx1,dy1,t->angle), rot_y(dx2,dy2,t->angle) ), 
  457.             max( rot_y(dx3,dy3,t->angle), rot_y(dx4,dy4,t->angle) ) );
  458.  
  459.     *xmin= t->base_x + 
  460.            min( min( rot_x(dx1,dy1,t->angle), rot_x(dx2,dy2,t->angle) ), 
  461.             min( rot_x(dx3,dy3,t->angle), rot_x(dx4,dy4,t->angle) ) );
  462.     *ymin= t->base_y + 
  463.            min( min( rot_y(dx1,dy1,t->angle), rot_y(dx2,dy2,t->angle) ), 
  464.             min( rot_y(dx3,dy3,t->angle), rot_y(dx4,dy4,t->angle) ) );
  465.     }
  466.  
  467. points_bound(points, xmin, ymin, xmax, ymax)
  468. F_point    *points;
  469. int    *xmin, *ymin, *xmax, *ymax;
  470. {
  471.     int    bx, by, sx, sy;
  472.     F_point    *p;
  473.  
  474.     bx = sx = points->x; by = sy = points->y;
  475.     for (p = points->next; p != NULL; p = p->next) {
  476.         sx = min(sx, p->x); sy = min(sy, p->y);
  477.         bx = max(bx, p->x); by = max(by, p->y);
  478.         }
  479.     *xmin = sx; *ymin = sy;
  480.     *xmax = bx; *ymax = by;
  481.     }
  482.  
  483. control_points_bound(cps, xmin, ymin, xmax, ymax)
  484. F_control    *cps;
  485. int        *xmin, *ymin, *xmax, *ymax;
  486. {
  487.     F_control    *c;
  488.     double        bx, by, sx, sy;
  489.  
  490.     bx = sx = cps->lx;
  491.     by = sy = cps->ly;
  492.     sx = min(sx, cps->rx); sy = min(sy, cps->ry);
  493.     bx = max(bx, cps->rx); by = max(by, cps->ry);
  494.     for (c = cps->next; c != NULL; c = c->next) {
  495.         sx = min(sx, c->lx); sy = min(sy, c->ly);
  496.         bx = max(bx, c->lx); by = max(by, c->ly);
  497.         sx = min(sx, c->rx); sy = min(sy, c->ry);
  498.         bx = max(bx, c->rx); by = max(by, c->ry);
  499.         }
  500.     *xmin = round(sx); *ymin = round(sy);
  501.     *xmax = round(bx); *ymax = round(by);
  502.     }
  503.